/**
 * 资源管理器 - 统一管理定时器、事件监听器、WebSocket连接等资源
 * 防止内存泄漏，确保组件卸载时正确清理所有资源
 */

type TimerType = 'timeout' | 'interval';

interface TimerInfo {
  id: number;
  type: TimerType;
  callback: Function;
  delay: number;
  created: number;
}

interface ListenerInfo {
  target: EventTarget;
  event: string;
  handler: EventListener;
  options?: boolean | AddEventListenerOptions;
}

interface ResourceInfo {
  id: string;
  type: 'timer' | 'listener' | 'websocket' | 'custom';
  resource: any;
  cleanup: () => void;
  created: number;
}

/**
 * 资源管理器类
 */
export class ResourceManager {
  private timers = new Map<number, TimerInfo>();
  private listeners = new Map<string, ListenerInfo>();
  private resources = new Map<string, ResourceInfo>();
  private destroyed = false;

  constructor(private name?: string) {
    this.name = name || `ResourceManager-${Math.random().toString(36).substr(2, 9)}`;
  }

  /**
   * 创建安全的setTimeout
   */
  setTimeout(callback: Function, delay: number = 0): number {
    if (this.destroyed) {
      console.warn(`${this.name}: 尝试在已销毁的ResourceManager中创建定时器`);
      return 0;
    }

    const id = window.setTimeout(() => {
      try {
        callback();
      } catch (error) {
        console.error(`${this.name}: 定时器回调执行错误:`, error);
      } finally {
        // 自动清理已执行的timeout
        this.timers.delete(id);
      }
    }, delay);

    this.timers.set(id, {
      id,
      type: 'timeout',
      callback,
      delay,
      created: Date.now()
    });

    return id;
  }

  /**
   * 创建安全的setInterval
   */
  setInterval(callback: Function, delay: number): number {
    if (this.destroyed) {
      console.warn(`${this.name}: 尝试在已销毁的ResourceManager中创建定时器`);
      return 0;
    }

    const id = window.setInterval(() => {
      try {
        callback();
      } catch (error) {
        console.error(`${this.name}: 定时器回调执行错误:`, error);
      }
    }, delay);

    this.timers.set(id, {
      id,
      type: 'interval',
      callback,
      delay,
      created: Date.now()
    });

    return id;
  }

  /**
   * 清除定时器
   */
  clearTimer(id: number): void {
    const timer = this.timers.get(id);
    if (!timer) return;

    if (timer.type === 'timeout') {
      clearTimeout(id);
    } else {
      clearInterval(id);
    }

    this.timers.delete(id);
  }

  /**
   * 添加事件监听器
   */
  addEventListener(
    target: EventTarget,
    event: string,
    handler: EventListener,
    options?: boolean | AddEventListenerOptions
  ): string {
    if (this.destroyed) {
      console.warn(`${this.name}: 尝试在已销毁的ResourceManager中添加事件监听器`);
      return '';
    }

    const listenerId = `${event}_${Math.random().toString(36).substr(2, 9)}`;

    target.addEventListener(event, handler, options);

    this.listeners.set(listenerId, {
      target,
      event,
      handler,
      options
    });

    return listenerId;
  }

  /**
   * 移除事件监听器
   */
  removeEventListener(listenerId: string): void {
    const listener = this.listeners.get(listenerId);
    if (!listener) return;

    listener.target.removeEventListener(listener.event, listener.handler, listener.options);
    this.listeners.delete(listenerId);
  }

  /**
   * 注册自定义资源
   */
  registerResource(
    id: string,
    resource: any,
    cleanup: () => void,
    type: 'websocket' | 'custom' = 'custom'
  ): void {
    if (this.destroyed) {
      console.warn(`${this.name}: 尝试在已销毁的ResourceManager中注册资源`);
      return;
    }

    this.resources.set(id, {
      id,
      type,
      resource,
      cleanup,
      created: Date.now()
    });
  }

  /**
   * 注销自定义资源
   */
  unregisterResource(id: string): void {
    const resource = this.resources.get(id);
    if (!resource) return;

    try {
      resource.cleanup();
    } catch (error) {
      console.error(`${this.name}: 清理资源 ${id} 时出错:`, error);
    }

    this.resources.delete(id);
  }

  /**
   * 获取资源统计
   */
  getStats() {
    return {
      name: this.name,
      timers: this.timers.size,
      listeners: this.listeners.size,
      resources: this.resources.size,
      destroyed: this.destroyed,
      details: {
        timers: Array.from(this.timers.values()).map((t) => ({
          id: t.id,
          type: t.type,
          delay: t.delay,
          age: Date.now() - t.created
        })),
        listeners: Array.from(this.listeners.values()).map((l) => ({
          event: l.event,
          target: l.target.constructor.name
        })),
        resources: Array.from(this.resources.values()).map((r) => ({
          id: r.id,
          type: r.type,
          age: Date.now() - r.created
        }))
      }
    };
  }

  /**
   * 检查是否有潜在的内存泄漏
   */
  checkForLeaks(): Array<{ type: string; message: string }> {
    const warnings: Array<{ type: string; message: string }> = [];
    const now = Date.now();
    const HOUR = 60 * 60 * 1000;

    // 检查长时间运行的定时器
    for (const timer of this.timers.values()) {
      const age = now - timer.created;
      if (age > HOUR) {
        warnings.push({
          type: 'timer',
          message: `定时器 ${timer.id} 已运行 ${Math.round(age / 60000)} 分钟，可能存在内存泄漏`
        });
      }
    }

    // 检查过多的事件监听器
    if (this.listeners.size > 50) {
      warnings.push({
        type: 'listener',
        message: `事件监听器数量过多 (${this.listeners.size})，可能存在内存泄漏`
      });
    }

    // 检查长时间存在的资源
    for (const resource of this.resources.values()) {
      const age = now - resource.created;
      if (age > HOUR * 2) {
        warnings.push({
          type: 'resource',
          message: `资源 ${resource.id} 已存在 ${Math.round(age / 60000)} 分钟，请检查是否需要清理`
        });
      }
    }

    return warnings;
  }

  /**
   * 销毁资源管理器，清理所有资源
   */
  destroy(): void {
    if (this.destroyed) {
      return;
    }

    console.log(`${this.name}: 开始清理所有资源...`);

    // 清理所有定时器
    for (const [id, timer] of this.timers) {
      if (timer.type === 'timeout') {
        clearTimeout(id);
      } else {
        clearInterval(id);
      }
    }
    this.timers.clear();

    // 清理所有事件监听器
    for (const listener of this.listeners.values()) {
      try {
        listener.target.removeEventListener(listener.event, listener.handler, listener.options);
      } catch (error) {
        console.error(`${this.name}: 移除事件监听器失败:`, error);
      }
    }
    this.listeners.clear();

    // 清理所有自定义资源
    for (const resource of this.resources.values()) {
      try {
        resource.cleanup();
      } catch (error) {
        console.error(`${this.name}: 清理资源 ${resource.id} 失败:`, error);
      }
    }
    this.resources.clear();

    this.destroyed = true;
    console.log(`${this.name}: 资源清理完成`);
  }

  /**
   * 检查是否已销毁
   */
  isDestroyed(): boolean {
    return this.destroyed;
  }
}

/**
 * Vue组合式API钩子，用于在组件中安全管理资源
 */
export function useResourceManager(name?: string) {
  const manager = new ResourceManager(name);

  // 组件卸载时自动清理
  if (typeof window !== 'undefined' && (window as any).Vue) {
    // 尝试获取当前实例进行自动清理
    try {
      const { onUnmounted } = (window as any).Vue;
      if (onUnmounted) {
        onUnmounted(() => {
          manager.destroy();
        });
      }
    } catch (error) {
      console.warn('无法自动注册onUnmounted钩子，请手动调用destroy()');
    }
  }

  return {
    // 定时器方法
    setTimeout: (callback: Function, delay?: number) => manager.setTimeout(callback, delay),
    setInterval: (callback: Function, delay: number) => manager.setInterval(callback, delay),
    clearTimer: (id: number) => manager.clearTimer(id),

    // 事件监听器方法
    addEventListener: (
      target: EventTarget,
      event: string,
      handler: EventListener,
      options?: boolean | AddEventListenerOptions
    ) => manager.addEventListener(target, event, handler, options),
    removeEventListener: (listenerId: string) => manager.removeEventListener(listenerId),

    // 资源管理方法
    registerResource: (
      id: string,
      resource: any,
      cleanup: () => void,
      type?: 'websocket' | 'custom'
    ) => manager.registerResource(id, resource, cleanup, type),
    unregisterResource: (id: string) => manager.unregisterResource(id),

    // 工具方法
    getStats: () => manager.getStats(),
    checkForLeaks: () => manager.checkForLeaks(),
    destroy: () => manager.destroy(),
    isDestroyed: () => manager.isDestroyed(),

    // 原始管理器实例（用于高级用法）
    manager
  };
}

// 全局资源管理器（用于全局资源）
export const globalResourceManager = new ResourceManager('Global');

// 页面卸载时清理全局资源
if (typeof window !== 'undefined') {
  window.addEventListener('beforeunload', () => {
    globalResourceManager.destroy();
  });

  window.addEventListener('pagehide', () => {
    globalResourceManager.destroy();
  });
}

export default ResourceManager;
